﻿using Colorful.Models;
using Colorful.CMS.Core;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Colorful.Database;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Colorful;

namespace Colorful
{
    public static class CMSHttpExtension
    {
        #region HttpContext

        #region 多语言相关

        #region 获取对应语言内容
        public static T GetLang<T>(this HttpContext context, T cn, T en)
        {
            if (context.GetLang() == LangEnum.CN.ToString())
                return cn;
            return en;
        }
        #endregion

        #region GetLang 获取当前语言
        public static string GetLang(this HttpContext context)
        {
            if (!context.Items.ContainsKey("Lang"))
            {
                var lang = $"{context.Request.Query["lang"]}".ToLower();
                if (!string.IsNullOrEmpty(lang) && lang == "en")
                {
                    lang = LangEnum.EN.ToString();
                }
                else if (context.Request.Path.HasValue && context.Request.Path.Value.ToLower().StartsWith("/en"))
                {
                    lang = LangEnum.EN.ToString();
                }
                else
                {
                    lang = LangEnum.CN.ToString();
                }
                context.Items.Add("Lang", lang);
            }
            return $"{context.Items["Lang"]}";
        }
        #endregion

        #region GetLink 生成中英文链接
        /// <summary>
        /// 根据指定链接获取带语言后缀的链接
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static string GetLink(this HttpContext context, string url)
        {
            if (string.IsNullOrEmpty(url))
                return context.Request.GetPathAndQuery();
            var isCN = context.GetLang() == LangEnum.CN.ToString();
            if (!isCN)
            {
                if (url.ToLower().Contains("lang="))
                {
                    url = Regex.Replace(url, "lang=cn", "lang=en");
                }
                else if (url.Contains("#") && !url.EndsWith("#"))
                {
                    if (url.Contains("?"))
                        url = Regex.Replace(url, "#", "&lang=en#");
                    else
                        url = Regex.Replace(url, "#", "?lang=en#");
                }
                else
                {
                    url += (url.Contains("?") ? "&" : "?") + "lang=en";
                }
            }
            return url;
        }
        #endregion

        #endregion

        #region 用户信息

        #region 登出
        public static async void SignOut(this HttpContext context)
        {
            await context.SignOutAsync(IdentityService.AuthenticationScheme);
            context.Session.Clear();
        }
        #endregion

        #region 获取TrackingId
        public static string GetTrackingId(this HttpContext context)
        {
            try
            {
                var trackingId = context.GetCookies("TrackingId");
                if (string.IsNullOrEmpty(trackingId))
                {
                    trackingId = WebService.GetUniqueId();
                    context.SetCookie("TrackingId", trackingId);
                }
                return trackingId;
            }
            catch
            {
                return null;
            }
        }
        #endregion

        #region GetClient 获取客户端信息
        public static Client GetClient(this HttpContext context)
        {
            if (!context.Items.ContainsKey("Client"))
            {
                var client = new Client(context.Request);
                context.Items.Add("Client", client);
            }
            return (Client)context.Items["Client"];
        }
        #endregion

        #region GetUserId 获取用户Id
        public static string GetUserId(this HttpContext context)
        {
            return context.User.GetId();
        }
        #endregion

        #region GetAppUser
        public static AppUser GetAppUser(this HttpContext context)
        {
            var userid = context.GetUserId();
            if (string.IsNullOrEmpty(userid))
                return null;
            var appUser = (AppUser)context.Items["AppUser"];
            if (appUser == null)
                appUser = CMSDbHelper.GetCache<AppUser>(userid);
            if (appUser == null)
            {
                throw new InvalidLoginException("访问被拒绝!");
            }
            else
                context.Items["AppUser"] = appUser;
            if (appUser.Roles == null)
                appUser.Roles = new List<long>();
            return appUser;
        }
        #endregion

        #region GetUserPermission 获取用户权限
        public static UserPermission GetUserPermission(this HttpContext context, AppUser user = null)
        {
            if (user == null)
                user = context.GetAppUser();
            if (user == null)
                return null;
            var userPermission = new UserPermission();
            using (var db = CMSDbHelper.GetDb())
            {
                if (user.LoginId == "admin")
                {
                    userPermission.Permissions.AddRange(db.Permissions.Select(a => a.Id).ToArray());
                    userPermission.Menus.AddRange(db.Menus.Select(a => a.Id).ToArray());
                }
                else
                {
                    var roles = db.Roles.ToList();
                    foreach (var roleId in user.Roles)
                    {
                        var role = roles.FirstOrDefault(a => a.Id == roleId);
                        if (role != null)
                        {
                            if (role.Menus != null && role.Menus.Count > 0)
                                userPermission.Menus.AddRange(role.Menus);
                            if (role.Permissions != null && role.Permissions.Count > 0)
                                userPermission.Permissions.AddRange(role.Permissions);
                        }
                    }
                }
            }
            return userPermission;
        }
        #endregion

        #region GetUserMenus 获取用户菜单
        public static List<MenuJson> GetUserMenus(this HttpContext context, int menuType, Func<List<long>, Menu, bool> filter)
        {
            //获取用户菜单
            var userPermission = context.GetUserPermission();
            if (userPermission == null)
                return null;
            var userMenus = userPermission.Menus;
            var showMenus = new List<MenuJson>();
            using (var db = CMSDbHelper.GetDb())
            {
                var allMenus = db.Menus.Where(a => a.Type == menuType).ToList();
                var ids = allMenus.Where(a => a.ParentId > 0 && userMenus.Contains(a.Id) && !userMenus.Contains(a.ParentId)).Select(a => a.ParentId).Distinct().ToArray();
                if (ids.Length > 0)
                    userMenus.AddRange(ids);
                var rootMenus = allMenus.Where(a => a.ParentId == 0).OrderBy(a => a.ByOrder).ToList();
                foreach (var menu in rootMenus)
                    FetchMenu(allMenus, menu, userMenus, showMenus, filter);
                return showMenus;
            }
        }
        private static void FetchMenu(List<Menu> allMenus, Menu menu, List<long> userMenus, List<MenuJson> showMenus, Func<List<long>, Menu, bool> filter)
        {
            if (!filter(userMenus, menu)) return;
            var menuJson = new MenuJson(menu);
            showMenus.Add(menuJson);
            var children = allMenus.Where(a => a.ParentId == menu.Id).OrderBy(a => a.ByOrder).ToList();
            if (children.Count > 0)
            {
                menuJson.children = new List<MenuJson>();
                foreach (var cMenu in children)
                    FetchMenu(allMenus, cMenu, userMenus, menuJson.children, filter);
            }
        }
        #endregion

        #region Login 用户登录
        public static async void Login(this HttpContext context, AppUser user)
        {
            await context.SignInAsync(IdentityService.AuthenticationScheme, IdentityService.GetIdentityUser(user), new AuthenticationProperties()
            {
                AllowRefresh = true,
                ExpiresUtc = DateTime.Now.AddHours(24).ToUniversalTime()
            });
            CMSDbHelper.SetCache(user.Id, user, TimeSpan.FromHours(24));
            context.Items["AppUser"] = user;
            //WebService.CacheService.Set($"#{user.Id}", user, TimeSpan.FromDays(365));
        }
        #endregion

        #endregion

        #endregion
    }
}
